## 文件时间：FILETIME包含一个 64 位值，该值表示自 1601年1月1日 (UTC) 以来的 100 纳秒间隔数。
## unix时间戳是从1970年1月1日（UTC/GMT的午夜）开始所经过的秒数，不考虑闰秒。
class_name FileTime
extends RefCounted

#region static and const
## 文件时间的起点1601-01-01
static var _fileTimeBeginningDict: Dictionary = { "year": 1601, "month": 1, "day": 1, "weekday": 1, "hour": 0, "minute": 0, "second": 0 }
## 文件时间的起点（相对unix时间起点1970-01-01经过的秒数：-11644473600）
static var _fileTimeBeginningValue: int = Time.get_unix_time_from_datetime_dict(_fileTimeBeginningDict)
## unix时间戳的七点1970-01-01
static var _unixTimeBeginningDict: Dictionary = { "year": 1970, "month": 1, "day": 1, "weekday": 1, "hour": 0, "minute": 0, "second": 0 }
## 毫秒到微秒的换算
const MS_TO_US: int = 1000
## 微妙到纳秒的换算
const US_TO_NS:int = 1000
## 毫秒到纳秒的换算
const MS_TO_NS: int = 1000000
## 秒到文件时间值（100纳秒）的换算
const SECOND_TO_FILETIME_VALUE = 1000 * 1000 * 10
#endregion static and const

#region GetUnixTime
## 将文件时间转换成unix时间戳
## 参数：
## fileTimeVal-文件时间值
## 返回：unix时间戳
static func GetUnixTimeFromFileTimeVal(fileTimeVal: int) -> int:
	@warning_ignore("integer_division")
	return  fileTimeVal / SECOND_TO_FILETIME_VALUE + _fileTimeBeginningValue

## 将文件时间字节数组转换成unix时间戳
## 参数：
## fileTimeBuffer-文件时间缓冲区
## 返回：unix时间戳
static func GetUnixTimeFromFileTimeBuffer(fileTimeBuffer: PackedByteArray) -> int:
	return GetUnixTimeFromFileTimeVal(fileTimeBuffer.decode_s64(0))
#endregion GetUnixTime

#region GetDateDict
## 将文件时间转换成日期字典，包含的键为：year、month、day、weekday。
## 参数：
## fileTimeVal-文件时间值
## 返回：日期字典
static func GetDateDictFromFileTimeVal(fileTimeVal: int) -> Dictionary:
	return Time.get_date_dict_from_unix_time(GetUnixTimeFromFileTimeVal(fileTimeVal))

## 将文件时间字节数组转换成日期字典，包含的键为：year、month、day、weekday。
## 参数：
## fileTimeBuffer-文件时间缓冲区
## 返回：日期字典
static func GetDateDictFromFileTimeBuffer(fileTimeBuffer: PackedByteArray) -> Dictionary:
	return Time.get_date_dict_from_unix_time(GetUnixTimeFromFileTimeBuffer(fileTimeBuffer))
#endregion GetDateDict

#region GetDateString
## 将文件时间转换为 ISO 8601 日期字符串（YYYY-MM-DD）。
## 参数：
## fileTimeVal-文件时间值
## 返回：日期字符串
static func GetDateStringFromFileTimeVal(fileTimeVal: int) -> String:
	return Time.get_date_string_from_unix_time(GetUnixTimeFromFileTimeVal(fileTimeVal))

## 将文件时间字节数组转换为 ISO 8601 日期字符串（YYYY-MM-DD）。
## 参数：
## fileTimeBuffer-文件时间缓冲区
## 返回：日期字符串
static func GetDateStringFromFileTimeBuffer(fileTimeBuffer: PackedByteArray) -> String:
	return Time.get_date_string_from_unix_time(GetUnixTimeFromFileTimeBuffer(fileTimeBuffer))
#endregion GetDateString

#region GetDateTimeDict
## 将文件时间转换为日期时间字典，包含的键为：year、month、day、weekday、hour、minute 和 second。
## 参数：
## fileTimeVal-文件时间值
## 返回：日期时间字典
static func GetDateTimeDictFromFileTimeVal(fileTimeVal: int) -> Dictionary:
	return Time.get_datetime_dict_from_unix_time(GetUnixTimeFromFileTimeVal(fileTimeVal))

## 将文件时间字节数组转换为字典，包含的键为：year、month、day、weekday、hour、minute 和 second。
## 参数：
## fileTimeBuffer-文件时间缓冲区
## 返回：日期时间字典
static func GetDateTimeDictFromFileTimeBuffer(fileTimeBuffer: PackedByteArray) -> Dictionary:
	return Time.get_datetime_dict_from_unix_time(GetUnixTimeFromFileTimeBuffer(fileTimeBuffer))
#endregion GetDateTimeDict

#region GetDateTimeString
## 将文件时间转换为 ISO 8601 日期和时间字符串（YYYY-MM-DDTHH:MM:SS）。
## 参数：
## fileTimeVal-文件时间值
## useSpace-当 useSpace 为 true 时，将使用空格代替中间的字母 T。
## 返回：日期时间字符串
static func GetDateTimeStringFromFileTimeVal(fileTimeVal: int, useSpace: bool = false) -> String:
	return Time.get_datetime_string_from_unix_time(GetUnixTimeFromFileTimeVal(fileTimeVal), useSpace)

## 将文件时间字节数组转换为 ISO 8601 日期和时间字符串（YYYY-MM-DDTHH:MM:SS）。
## 参数：
## fileTimeBuffer-文件时间缓冲区
## useSpace-当 useSpace 为 true 时，将使用空格代替中间的字母 T。
## 返回：日期时间字符串
static func GetDateTimeStringFromFileTimeBuffer(fileTimeBuffer: PackedByteArray, useSpace: bool = false) -> String:
	return Time.get_datetime_string_from_unix_time(GetUnixTimeFromFileTimeBuffer(fileTimeBuffer), useSpace)
#endregion GetDateTimeString

#region GetTimeDict
## 将文件时间转换为时间字典，包含的键为：时 hour、分 minute、秒 second。
## 参数：
## fileTimeVal-文件时间值
## 返回：时间字典
static func GetTimeDictFromFileTimeVal(fileTimeVal: int) -> Dictionary:
	return Time.get_time_dict_from_unix_time(GetUnixTimeFromFileTimeVal(fileTimeVal))

## 将文件时间字节数组转换为时间字典，包含的键为：时 hour、分 minute、秒 second。
## 参数：
## fileTimeBuffer-文件时间缓冲区
## 返回：时间字典
static func GetTimeDictFromFileTimeBuffer(fileTimeBuffer: PackedByteArray) -> Dictionary:
	return Time.get_time_dict_from_unix_time(GetUnixTimeFromFileTimeBuffer(fileTimeBuffer))
#endregion GetTimeDict

#region GetTimeString
## 将文件时间转换为 ISO 8601 时间字符串（HH:MM:SS）。
## 参数：
## fileTimeVal-文件时间值
## 返回：时间字符串
static func GetTimeStringFromFileTimeVal(fileTimeVal: int) -> String:
	return Time.get_time_string_from_unix_time(GetUnixTimeFromFileTimeVal(fileTimeVal))

## ## 将文件时间字节数组转换为 ISO 8601 时间字符串（HH:MM:SS）。
## 参数：
## fileTimeBuffer-文件缓冲区
## 返回：时间字符串
static func GetTimeStringFromFileTimeBuffer(fileTimeBuffer: PackedByteArray) -> String:
	return Time.get_time_string_from_unix_time(GetUnixTimeFromFileTimeBuffer(fileTimeBuffer))
#endregion GetTimeString

#region GetFileTime
## 将文件时间转换成字节数组
## 参数：
## fileTimeVal-文件时间值
## 返回：文件时间字节数组
static func GetFileTimeBuffer(fileTimeVal: int) -> PackedByteArray:
	var buffer: PackedByteArray = PackedByteArray()
	buffer.resize(8)
	buffer.encode_s64(0, fileTimeVal)
	return buffer

## 将unix时间戳转换成文件时间
## 参数：
## fileTimeVal-unix时间戳
## 返回：文件时间值
static func GetFileTimeValFromUnixTime(unixTimeVal: int) -> int:
	return (unixTimeVal - _fileTimeBeginningValue) * SECOND_TO_FILETIME_VALUE

## 将unix时间戳转换成文件时间字节数组
## 参数：
## fileTimeVal-unix时间戳
## 返回：文件时间字节数组
static func GetFileTimeBufferFromUnixTime(unixTimeVal: int) -> PackedByteArray:
	return GetFileTimeBuffer(GetFileTimeValFromUnixTime(unixTimeVal))

## 将时间值字典转换为文件时间。
## 参数：
## datetime-给定的字典可以包含以下键：year、month、day、hour、minute、second。其他的记录（包括 dst）都会被忽略。
## 字典为空时将返回 11644473600000。如果省略了部分键，默认使用 Unix 纪元时间戳 0（1970-01-01 的 00:00:00）的对应部分。
## 返回：文件时间值
## 注意：Unix 时间戳通常是 UTC 的。本方法不会做任何时区转换，所以时间戳的时区与给定的日期时间字典相同。
static func GetFileTimeValFromDatetimeDict(datetime: Dictionary) -> int:
	return GetFileTimeValFromUnixTime(Time.get_unix_time_from_datetime_dict(datetime))

## 将时间值字典转换为文件时间字节数组。
## 参数：
## datetime-给定的字典可以包含以下键：year、month、day、hour、minute、second。其他的记录（包括 dst）都会被忽略。
## 字典为空时将返回 11644473600000。如果省略了部分键，默认使用 Unix 纪元时间戳 0（1970-01-01 的 00:00:00）的对应部分。
## 返回：文件时间字节数组
## 注意：Unix 时间戳通常是 UTC 的。本方法不会做任何时区转换，所以时间戳的时区与给定的日期时间字典相同。
static func GetFileTimeBufferFromDatetimeDict(datetime: Dictionary) -> PackedByteArray:
	return GetFileTimeBufferFromUnixTime(Time.get_unix_time_from_datetime_dict(datetime))

## 将给定的 ISO 8601 日期和/或时间字符串转换为文件时间。字符串中可以只包含日期、只包含时间，也可以两者都包含。
## 参数：
## datetime-日期（时间）字符串
## 返回：文件时间值。
## 注意：时间字符串中的小数会被静默忽略。
static func GetFileTimeValFromDatetimeString(datetime: String) -> int:
	return GetFileTimeValFromUnixTime(Time.get_unix_time_from_datetime_string(datetime))

## 将给定的 ISO 8601 日期和/或时间字符串转换为文件时间字节数组。字符串中可以只包含日期、只包含时间，也可以两者都包含。
## 参数：
## datetime-日期（时间）字符串
## 返回：文件时间字节数组。
## 注意：时间字符串中的小数会被静默忽略。
static func GetFileTimeBufferFromDatetimeString(datetime: String) -> PackedByteArray:
	return GetFileTimeBufferFromUnixTime(Time.get_unix_time_from_datetime_string(datetime))
	
## 以文件时间形式返回当前日期。
## 参数：
## utc-当 utc 为 false 时，返回的是系统的本地时间，否则为 UTC 时间。
## 返回：文件时间值。
static func GetFileTimeValFromSystem(utc: bool = false) -> int:
	return GetFileTimeValFromDatetimeDict(Time.get_datetime_dict_from_system(utc))
	
## 以文件时间形式返回当前日期。
## 参数：
## utc-当 utc 为 false 时，返回的是系统的本地时间，否则为 UTC 时间。
## 返回：文件时间字节数组。
static func GetFileTimeBufferFromSystem(utc: bool = false) -> PackedByteArray:
	return GetFileTimeBufferFromDatetimeDict(Time.get_datetime_dict_from_system(utc))
#endregion GetFileTime

#region Test
static func Test() -> void:
	var now = Time.get_datetime_dict_from_system()
	var nowUnixValue = Time.get_unix_time_from_datetime_dict(now)
	var nowFileTimeValue = FileTime.GetFileTimeValFromDatetimeDict(now)
	var now2 = FileTime.GetDateTimeDictFromFileTimeVal(nowFileTimeValue)
	print(now, ",", nowUnixValue, ",", nowFileTimeValue, ",", now2)
	var nowFileTimeBuffer: PackedByteArray = FileTime.GetFileTimeBufferFromDatetimeDict(now)
	var nowFileTimeValue3 = nowFileTimeBuffer.decode_s64(0)
	var now3 = FileTime.GetDateTimeDictFromFileTimeBuffer(nowFileTimeBuffer)
	print(now, ",", nowFileTimeBuffer, ",", nowFileTimeValue3, ",", now3)
	print("测试结果：", "通过" if nowFileTimeValue == nowFileTimeValue3 else "不通过")
#endregion Test
